package docker

import (
	"encoding/json"
	"os"
	"os/exec"
	"runtime"
	"strings"
	"time"

	"gitee.com/extrame/fb-runner/util"
	"github.com/pkg/errors"
	"github.com/sirupsen/logrus"
)

//获得所有运行中的服务列表
func Services(source, base, networkName string, useCouchdb, useCa bool) ([]string, error) {

	// util.Mkdir(filepath.Join(base, "/organizations/fabric-ca/org1"))
	// util.Mkdir(filepath.Join(base, "/organizations/fabric-ca/org2"))
	// util.Mkdir(filepath.Join(base, "/organizations/fabric-ca/order"))
	// copy docker-compose file

	var cfgs = []string{"docker/docker-compose-test-net.yaml"}

	if useCouchdb {
		cfgs = append(cfgs, "docker/docker-compose-couch.yaml")
	}
	if useCa {
		cfgs = append(cfgs, "docker/docker-compose-ca.yaml")
	}

	var args []string

	for _, c := range cfgs {
		args = append(args, "-f", c)
	}

	args = append(args, "-p", networkName, "ps", "--service")

	cmd := exec.Command("docker-compose", args...)
	cmd.Dir = base
	output, _, err := util.Run(cmd)
	services := strings.Split(output, "\n")
	return services, err
}

func ExportLog(service string, since time.Time, dest string) (until time.Time, err error) {

	var args = []string{"logs"}
	var containerInfos map[string]*ContainerInfo

	if since.IsZero() {
		containerInfos, err = ps()
		if err != nil {
			return time.Time{}, err
		}
		if info, ok := containerInfos[service]; ok {
			since, err = time.Parse("2006-01-02 15:04:05 -0700 MST", info.CreatedAt)
			if err != nil {
				return time.Time{}, err
			}
		} else {
			err = errors.New("没有这个service")
			logrus.WithField("services", containerInfos).Errorln(err)
			return time.Time{}, err
		}
	}

	var f *os.File
	f, err = os.OpenFile(dest, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
	var gotted = false
	defer f.Close()
	if err == nil {
		for {
			until = since.Add(24 * time.Hour)
			logrus.WithField("since", since).WithField("until", until).WithField("service", service).Infoln("got logs")
			single := append(args, "--since", since.Format(time.RFC3339))
			single = append(single, "--until", until.Format(time.RFC3339))

			single = append(single, service)

			cmd := exec.Command("docker", single...)
			var output string
			_, output, err = util.Run(cmd)
			if err == nil && len(output) > 0 {
				gotted = true
				_, err = f.WriteString(output)
			}
			if (gotted && len(output) == 0) || err != nil {
				break
			} else if until.After(time.Now()) {
				return time.Now(), nil
			} else {
				since = until
			}
		}
	}

	return
}

func ps() (infos map[string]*ContainerInfo, err error) {
	cmdPs := exec.Command("docker", "ps", "--format", "{{json . }}")
	bts, _, err := util.Run(cmdPs)

	if err == nil {

		if bts == "" {
			err = errors.New("没有安装fabric相关docker文件，请检查安装")
			goto respondErr
		}

		var sep = "\n"
		if runtime.GOOS == "windows" {
			sep = "\r\n"
		}
		infos = make(map[string]*ContainerInfo)
		lines := strings.Split(bts, sep)
		for _, line := range lines {
			if len(line) > 0 {
				var info ContainerInfo
				err = json.Unmarshal([]byte(line), &info)
				if err != nil {
					return nil, errors.Wrap(err, "in unmarshal "+line)
				}
				infos[info.Names] = &info
			}
		}
	}
respondErr:
	return
}

type ContainerInfo struct {
	Names     string
	CreatedAt string
}
